/**
 * This is webServer's User module that handles URL /user/*
 */

// Express router

//import package
const router = require("express").Router();
//import utilities
const jwt = require("jsonwebtoken");
const { isValidateRegistration } = require("./utilities/userUtil.js");
const { jwtConfig, authenticateToken } = require("./utilities/jwtUtils.js");
// Logging
const { log } = require("./utilities/common.js");
const {
  makePasswordEntry,
  doesPasswordMatch,
} = require("../lib/lilywebPassword.js");
//import package
//导入schema
const User = require("../schema/userSchema");

/**
 * URL: /user/login
 * Handle the login request.
 * @param {Object} request - HTTP请求对象
 * @param {Object} response - HTTP响应对象
 * @returns {Object<string>} 用户信息对象或响应错误信息
 */
router.post("/login", async function (request, response) {
  try {
    const { account, password } = request.body;
    let personObj = await User.findOne({ account: account });
    console.log(personObj);
    if (password && password.length > 0) {
      if (personObj) {
        if (
          !doesPasswordMatch(
            personObj.password_digest,
            personObj.salt,
            password
          )
        ) {
          response.status(400).send("Wrong user name or password");
          return;
        }
        //生成access_token
        const accessToken = jwt.sign(
          {
            id: personObj._id,
            nickname: personObj.nickname,
          },
          jwtConfig.jwtSecretKey,
          {
            expiresIn: jwtConfig.expiresIn,
          }
        );
        //生成refreshToken
        const refreshToken = jwt.sign(
          {
            id: personObj._id,
            nickname: personObj.nickname,
          },
          jwtConfig.jwtSecretKey,
          {
            expiresIn: jwtConfig.LongExpiresIn,
          }
        );
        // Convert user data
        personObj = JSON.parse(JSON.stringify(personObj));
        //TODO是否存session

        //删除哈希值和盐
        delete personObj.salt;
        delete personObj.hash;

        //返回给客户端
        const outcome = {
          code: 200,
          msg: "登录成功",
          userInfo: personObj,
          accessToken: accessToken,
          refreshToken: refreshToken,
        };
        response.status(outcome.code).send(outcome);
      } else {
        response.status(401).send("User not found");
      }
    }
  } catch (error) {
    console.log(error);
    response.status(500).json({ error: "Internal server error" });
  }
});
/**
 * URL: /user/register
 * Handle the Register request.
 * @param {Object} request - HTTP请求对象
 * @param {Object} response - HTTP响应对象
 * @returns {Object|string} 响应错误信息
 */
router.post("/register", async function (request, response) {
  // 获取请求体对象
  const newUserData = request.body;
  // 进行表单验证
  const errors = isValidateRegistration(newUserData); // 使用 await
  if (errors.length === 0) {
    try {
      // 判断是否数据库已经存在该用户对象
      const isExistNickName = await User.findOne({
        nickname: newUserData.nickname,
      });
      const isExistAccount = await User.findOne({
        account: newUserData.account,
      });
      if (!isExistNickName && !isExistAccount) {
        const passwordData = makePasswordEntry(newUserData.password);
        // 创建新用户对象
        const newUser = new User({
          nickname: newUserData.nickname,
          account: newUserData.account,
          password_digest: passwordData.hash,
          salt: passwordData.salt,
        });
        // 存入数据库当中
        const savedUser = await newUser.save();
        response.status(200).send(`User: ${savedUser.nickname} register`); // 使用 savedUser
      } else {
        response.status(401).send("User is exist");
      }
    } catch (err) {
      console.error(err);
      response.status(500).send({ error: "Internal server error" });
    }
  } else {
    // 注册表单错误
    console.error(errors);
    response.status(400).send({ errors: errors }); // 发送具体的错误信息
  }
});
/**
 * URL: /user/logout
 * Handle the Register request.
 * @param {Object} request - HTTP请求对象
 * @param {Object} response - HTTP响应对象
 * @returns {Object|string} 响应错误信息
 */
//TODO可能需要验证信息，写的过于简单
router.post("/logout", async function (request, response) {
  try {
    // 清除客户端存储的令牌
    // 这里通常使用 localStorage 或 sessionStorage
    // 请注意，服务器端无法直接访问客户端存储，因此需要客户端配合
    response.status(200).send("User logged out");
  } catch (error) {
    console.error(error);
    response.status(500).send({ error: "Internal server error" });
  }
});

/**
 * URL: /user/refresh
 * Handle the Register request.
 * @param {Object} request - HTTP请求对象
 * @param {Object} response - HTTP响应对象
 * @returns {Object|string} 响应错误信息
 */
router.get("/refresh", async function (request, response) {
  try {
    const { refreshToken } = request.query;
    // 验证刷新令牌是否存在且有效
    const decoded = jwt.verify(refreshToken, jwtConfig.jwtSecretKey);
    if (!decoded) {
      return response.status(401).send("Invalid or expired refresh token");
    }

    // 检查数据库中用户信息是否匹配刷新令牌中的信息
    const user = await User.findOne({ _id: decoded.id });
    if (!user) {
      return response.status(401).send("User not found");
    }

    // 生成新的访问令牌
    const newAccessToken = jwt.sign(
      {
        id: user._id,
        nickname: user.nickname,
      },
      jwtConfig.jwtSecretKey,
      {
        expiresIn: jwtConfig.expiresIn,
      }
    );

    // 出于安全考虑，通常每次刷新令牌时都会生成一个新的刷新令牌
    const newRefreshToken = jwt.sign(
      {
        id: user._id,
        nickname: user.nickname,
      },
      jwtConfig.jwtSecretKey,
      {
        expiresIn: jwtConfig.LongExpiresIn,
      }
    );

    // 返回新的访问令牌和刷新令牌
    const outcome = {
      code: 200,
      msg: "Token refreshed successfully",
      accessToken: newAccessToken,
      refreshToken: newRefreshToken,
    };
    return response.status(200).send(outcome);
  } catch (error) {
    console.error(error);
    return response.status(500).json({ error: "Internal server error" });
  }
});

/**
 * URL: /user/interface
 * change user interface
 * @async
 * @param {Object} request - HTTP请求对象
 * @param {Object} response - HTTP响应对象
 * @returns {string} 响应信息
 */
router.post("/interface", authenticateToken, async (request, response) => {
  const newInterface = request.body;
  const id = request.userId;
  try {
    log.info("update user interface:", id, newInterface);
    const updatedUser = await User.findByIdAndUpdate(
      id,
      { $set: { interface: newInterface } },
      { new: true, runValidators: true }
    );

    if (!updatedUser) {
      throw new Error("User not found or update failed");
    }

    log.info("Successfully updated user interface.");
    return response.status(200).send("Updated user interface"); // 直接返回字符串
  } catch (error) {
    log.error("Fail to update user interface.", error);
    return response.status(400).send("Fail to update user interface."); // 直接返回错误信息
  }
});
/**
 * URL: /user/info
 * change user info
 * @async
 * @param {Object} request - HTTP请求对象
 * @param {Object} response - HTTP响应对象
 * @returns {string} 响应信息
 */
router.get("/info", authenticateToken, async (request, response) => {
  const id = request.userId;
  try {
    log.info("user id is:", id);
    let personObj = await User.findById(id);
    if (!personObj) {
      // Query returned null.
      throw new Error(`Can not find user ${id}`);
    }
    //TODO安全检查模块
    response.status(200).send(personObj);
  } catch (error) {
    log.error(`Could not get user info ${id}`, error);
    response.status(400).send("Could not get user info");
  }
});

module.exports = router;
